package com.example.bootflowable.controller;

import com.example.bootflowable.utils.ResObject;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/flowable")
public class FlowableController {

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @GetMapping("/deploy222")
    public ResObject de(@RequestParam("name") String name) {

        System.out.println(name);

        return new ResObject("success");
    }

    @GetMapping("/deploy")
    public ResObject deploy(String fileName) {
        //部署流程
        Deployment deploy = repositoryService.createDeployment().addClasspathResource(fileName).deploy();
        //查找部署流程的定义
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploy.getId()).singleResult();

        Map<String, Object> variables = new HashMap<>(16);
        variables.put("nextUser1", "张三");
        variables.put("nextUser2", "李四");
        variables.put("nextUser3", "王五");
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(), variables);

        return new ResObject(processInstance.getProcessInstanceId());
    }

    @GetMapping("/find")
    public ResObject find(String userName) {
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(userName).list();
        List<MyTask> myTasks = new ArrayList<>(tasks.size());
        tasks.forEach(item -> {
            MyTask myTask = new MyTask();
            BeanUtils.copyProperties(item, myTask);
            myTasks.add(myTask);
        });
        return new ResObject(myTasks);
    }

    @GetMapping("/agree")
    public ResObject agree(String taskId) {
        taskService.complete(taskId);
        return new ResObject();
    }

    @GetMapping("/reject")
    public ResObject reject(String processInstanceId,  String executionId) {
        String currentActivityId = runtimeService.getActiveActivityIds(executionId).get(0);
        String lastActivityId = getLastActivityId(processInstanceId, currentActivityId);
        //回退了 流程
        runtimeService.createChangeActivityStateBuilder()
                .processInstanceId(processInstanceId)
                .moveActivityIdTo(currentActivityId, lastActivityId)
                .changeState();

        return new ResObject();
    }


    private String getLastActivityId(String processInstanceId, String currentActivityId) {

        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processInstanceId)
                .finished()
                .activityType("userTask")
                .orderByHistoricActivityInstanceStartTime().desc()
                .list();


        String lastActivityId = null;
        //找到上一个流程的 activityId
        for (int i=0; i<list.size(); i++) {
            HistoricActivityInstance activityInstance = list.get(i);
            if(activityInstance.getActivityId().equals(currentActivityId)) {
                lastActivityId = list.get(++i).getActivityId();
                break;
            }
        }

        if(lastActivityId == null) {
            lastActivityId = list.get(0).getActivityId();
        }

        return lastActivityId;
    }

}
